//--------------------------------------------------------------
//
// Qizhi Zhang 
// ezhung@gmail.com
// http://www.moorwind.com
//
//--------------------------------------------------------------
package reader.utils
{
	import __AS3__.vec.Vector;
	
	import com.adobe.xml.syndication.generic.FeedFactory;
	import com.adobe.xml.syndication.generic.IFeed;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import reader.core.ReaderError;
	import reader.core.ReaderModelLocator;
	import reader.core.ReaderResource;
	import reader.events.FeedLoaderEvent;
	import reader.model.vo.BlogItemVO;
	import reader.model.vo.BlogSourceVO;
	import reader.model.vo.ServiceVO;
	
	[Event(name="feedInit", type="reader.events.FeedLoaderEvent")]	 
	[Event(name="feedLoad", type="reader.events.FeedLoaderEvent")]	 
	[Event(name="feedFail", type="reader.events.FeedLoaderEvent")]	 

	public class FeedLoader extends EventDispatcher
	{
		//////////////////////////////////////////////////////////////////////////////
		//Public properties
		
		public var blogSource:BlogSourceVO;
		
		//////////////////////////////////////////////////////////////////////////////
		//Private properties
		
		private var isInitBlogSource:Boolean;
		
		//////////////////////////////////////////////////////////////////////////////
		//Constructor
		public function FeedLoader(blogSource:BlogSourceVO = null)
		{
			this.blogSource = blogSource;
		}
		
		//////////////////////////////////////////////////////////////////////////////
		//methods
		public function loadFeed(isInitBlogSource:Boolean = false):void
		{
			this.isInitBlogSource = isInitBlogSource;
			
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onFeedsLoaded_handler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onFeedsLoadError_handler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onFeedsLoadError_handler);
			loader.load(new URLRequest(this.blogSource.blogRSS));
		}
		
		public static function getBlogSourceByFeed(feedString:String):BlogSourceVO
		{
			var xml:XML;
			var feed:IFeed; 
			
			try
			{
				xml = new XML(feedString);
			}
			catch(e:Error)
			{			
				return null;
			}
			
			try
			{
				feed = FeedFactory.getFeedByXML(xml);
			}
			catch(e:Error)
			{
				
				return null;
			}
			
			return GetBlogSourceByFeed(feed);
		}
		
		public static function GetBlogSourceByFeed(feed:IFeed):BlogSourceVO
		{
			var bs:BlogSourceVO = new BlogSourceVO();
			bs.blogLink = feed.metadata.link;
			if(!feed.metadata.title || StringUtils.trimAll(feed.metadata.title) == "")
			{
				if(!feed.metadata.description || StringUtils.trimAll(feed.metadata.description) == "")
					bs.blogName = bs.blogLink;
				else
					bs.blogName = StringUtils.trimAll(feed.metadata.description);
			}
			else
				bs.blogName = feed.metadata.title;
			bs.labelId = -1;
			bs.lastPubDate = feed.metadata.date ? feed.metadata.date : BlogSourceVO.createLastPubDate();
			return bs;
		}
		
		//////////////////////////////////////////////////////////////////////////////
		//events
		
		private function onFeedsLoaded_handler(e:Event):void
		{
			var loader:URLLoader = e.target as URLLoader;
			loader.removeEventListener(Event.COMPLETE, onFeedsLoaded_handler);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onFeedsLoadError_handler);
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onFeedsLoadError_handler);
			
			var i:int;
			var xml:XML;
			var feed:IFeed;
			var blog:BlogItemVO;
			var blogArray:Vector.<BlogItemVO> = new Vector.<BlogItemVO>();
			var failEvent:FeedLoaderEvent = new FeedLoaderEvent(FeedLoaderEvent.FEED_FAIL);
			failEvent.blogSource = this.blogSource;
			try
			{
				xml = new XML(e.target.data);
			}
			catch(e:Error)
			{
				this.dispatchEvent(failEvent);
				return;
			}
			
			try
			{
				feed = FeedFactory.getFeedByXML(xml);
			}
			catch(e:Error)
			{
				this.dispatchEvent(failEvent);
				return;
			}
			
			for(i = 0; i < feed.items.length; i++)
			{
				blog = new BlogItemVO();
				blog.blogSourceId = blogSource.blogSourceId;
				blog.title = feed.items[i].title;
				blog.link = feed.items[i].link;
				blog.guid = feed.items[i].id;
				blog.description = feed.items[i].excerpt.value;
				blog.pubDate = feed.items[i].date;
				
				if(feed.items[i].authors[0].name) blog.authors = feed.items[i].authors[0].name;
				else if(feed.items[i].authors[0].email) blog.authors = feed.items[i].authors[0].email;
				else if(feed.items[i].authors[0].url) blog.authors = feed.items[i].authors[0].url;
				else blog.authors = ReaderResource.instance.resource.blogItemUnknowAuthor;
				
				blogArray.push(blog);
				
			}
			blogArray.sort(BlogItemVO.sortBlogByPubDate);
			var feedLoaderEvent:FeedLoaderEvent = new FeedLoaderEvent(isInitBlogSource ? FeedLoaderEvent.FEED_INIT: FeedLoaderEvent.FEED_LOAD);
			feedLoaderEvent.blogSource = this.blogSource;
			feedLoaderEvent.blogItems = blogArray;
			this.dispatchEvent(feedLoaderEvent);
		}
		
		private function onFeedsLoadError_handler(e:IOErrorEvent):void
		{
			var loader:URLLoader = e.target as URLLoader;
			loader.removeEventListener(Event.COMPLETE, onFeedsLoaded_handler);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onFeedsLoadError_handler);
			var failEvent:FeedLoaderEvent = new FeedLoaderEvent(FeedLoaderEvent.FEED_FAIL);
			failEvent.blogSource = this.blogSource;
			this.dispatchEvent(failEvent);
		}
		
		public static function GetFeedsURI(section:String, post:*, service:ServiceVO = null, sourece:XML = null):String
		{
			if(sourece == null) sourece = ReaderModelLocator.instance.subscribeConfig;
			var list:XMLList = sourece.config.(@name == section);
			if(list.length() == 0 || list.length() > 1)
			{
				throw new ReaderError(ReaderError.SUBSCRIBE_CONFIG_ERROR);
			}
			var target:XML = list[0];
			if(post is String)
			{
				return target.endpoint.toString().replace(new RegExp(target.methods.reg[0].@r, target.methods.reg[0].@f), post);
			}
			else
			{
				var result:String = target.endpoint.toString();
				for each(var xml:XML in target.methods.reg)
				{
					if(String(xml.@c) == "Post")
					{
						result = result.replace(new RegExp(xml.@r, xml.@f), post[String(xml.@s)]);
					}
					else if(String(xml.@c) == "Service")
					{
						result = result.replace(new RegExp(xml.@r, xml.@f), service[String(xml.@s)]);
					}
				}
				
				return result;
			}
		}

	}
}